﻿//Copyright (c) 2010 Christopher E. S. King (http://chriskingconsulting.com)
//
//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files 
// (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, 
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do 
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Diagnostics.Contracts;
using System.Text.RegularExpressions;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Xml;
using System.Xml.Linq;
using System.Runtime.InteropServices;

using King.Extensions;

namespace King.Any {

    [StructLayout(LayoutKind.Explicit)]
    internal struct AnyPrimitive {

        [FieldOffset(0)]internal bool m_bool;
        [FieldOffset(0)]internal char m_char;

        [FieldOffset(0)]internal sbyte m_sbyte;
        [FieldOffset(0)]internal short m_short;
        [FieldOffset(0)]internal int m_int;
        [FieldOffset(0)]internal long m_long;

        [FieldOffset(0)]internal byte m_byte;
        [FieldOffset(0)]internal ushort m_ushort;
        [FieldOffset(0)]internal uint m_uint;
        [FieldOffset(0)]internal ulong m_ulong;

        [FieldOffset(0)]internal double m_double;
        [FieldOffset(0)]internal float m_float;

    }

    public struct Any {

        private Type m_type;
        private AnyPrimitive m_primitive;
        private object m_object;

        private Any(Type type) {
            this = default(Any);
            m_type = type;
        }

        Any(bool value) : this(value.GetType()) { m_primitive.m_bool = value; }
        Any(char value) : this(value.GetType()) { m_primitive.m_char = value; }

        Any(sbyte value) : this(value.GetType()) { m_primitive.m_sbyte = value; }
        Any(short value) : this(value.GetType()) { m_primitive.m_short = value; }
        Any(int value) : this(value.GetType()) { m_primitive.m_int = value; }
        Any(long value) : this(value.GetType()) { m_primitive.m_long = value; }

        Any(byte value) : this(value.GetType()) { m_primitive.m_byte = value; }
        Any(ushort value) : this(value.GetType()) { m_primitive.m_ushort = value; }
        Any(uint value) : this(value.GetType()) { m_primitive.m_uint = value; }
        Any(ulong value) : this(value.GetType()) { m_primitive.m_ulong = value; }

        Any(double value) : this(value.GetType()) { m_primitive.m_double = value; }
        Any(float value) : this(value.GetType()) { m_primitive.m_float = value; }

        private void CheckType(Type type) {
            if (type != m_type)
                throw new InvalidOperationException();
        }

        public bool Boolean { get { CheckType(typeof(bool)); return m_primitive.m_bool; } }
        public char Character { get { CheckType(typeof(char)); return m_primitive.m_char; } }

        public sbyte SignedByte { get { CheckType(typeof(sbyte)); return m_primitive.m_sbyte; } }
        public short Short { get { CheckType(typeof(short)); return m_primitive.m_short; } }
        public int Integer { get { CheckType(typeof(int)); return m_primitive.m_int; } }
        public long Long { get { CheckType(typeof(long)); return m_primitive.m_long; } }

        public byte Byte { get { CheckType(typeof(byte)); return m_primitive.m_byte; } }
        public ushort UnsignedShort { get { CheckType(typeof(ushort)); return m_primitive.m_ushort; } }
        public uint UnsignedInt { get { CheckType(typeof(uint)); return m_primitive.m_uint; } }
        public ulong UnsignedLong { get { CheckType(typeof(ulong)); return m_primitive.m_ulong; } }

        public double Double { get { CheckType(typeof(double)); return m_primitive.m_double; } }
        public float Float { get { CheckType(typeof(float)); return m_primitive.m_float; } }
    }
}
